#pragma once
#include <algorithm>
#include <typeinfo>
#include <cassert>


using namespace std;

class Any {
public:
    Any()
       : _val(nullptr)
    {
        cout << "Any()" << endl;
    }

    Any(const Any &other) {
        cout << "Any(const Any &other)" << endl;
        if (this != &other) {
            // 深拷贝
            _val = other._val == nullptr ? nullptr : other._val->clone();
        }
    }

    template<class T>
    Any(const T &val) 
        : _val(new derived<T>(val))
    {
        cout << "Any(const T &val)" << endl;
    }
 
    void swap(Any other) {
        std::swap(_val, other._val);
    }

    Any &operator=(const Any &other) {
        cout << "Any &operator=(const Any &other)" << endl;
        if (this != &other) {
            swap(other);
        }
        return *this;
    }
    
    template<class T>
    Any &operator=(const T &v) {
        cout << "Any &operator=(const T &v)" << endl;
        swap(v);
        return *this;
    } 

    template<class T>
    T* get() const {
        // 先判断类型是否一致
        assert(typeid(T) == _val->type());
        derived<T> *d = dynamic_cast<derived<T> *>(_val);
        return d == nullptr ? nullptr : d->get();
    }

    ~Any() {
        cout << "~Any()" << endl;
        delete _val;
    }

private:
    class base {
    public:
        virtual ~base() {
            // 保证所有子类都有析构函数
        }
        virtual const type_info& type() const = 0;
        virtual base* clone() const = 0;
    };

    template<class T>
    class derived : public base {
    public:
        derived(const T &val) 
            :_val(val)
        {}

        // 获取子类保存的数据类型
        virtual const type_info& type() const {
            return typeid(_val);
        }

        //  复制一个子类对象
        virtual base* clone() const {
            return new derived(*this);
        }
    
        T* get() {
            return &_val;
        }

    private:
        T _val;
    };

private:
    base *_val;
};
